package br.com.fogas.impressora;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import br.com.fogas.database.entidade.Cliente;
import br.com.fogas.database.entidade.NotaFiscal;
import br.com.fogas.database.entidade.NotaItem;
import br.com.fogas.impressora.ImpressoraMPT_Builder.ALIGN;
import br.com.fogas.modelo.FogasDados;
import br.com.fogas.notafiscal.DescontosDto;
import br.com.fogas.notafiscal.NotaFiscalEngine;
import br.com.fogas.utils.FogasUtility;
import br.com.fogas.utils.StringUtility;

public class ImpressaoNotaBuilder {

	private String naturezaOperacao = StringUtility.EMPTY;
	
	private String cfop = StringUtility.EMPTY;
	
	private String nfNumero = StringUtility.EMPTY;
	
	private String nfSerie = StringUtility.EMPTY;
	
	private String via = StringUtility.EMPTY;
	
	private boolean emitidaContigencia = false;
	
	private String chaveAcesso = StringUtility.EMPTY;
	
	private String protocoloAutorizacao = StringUtility.EMPTY;
	
	private FogasDados emitente = null;
	
	private String emissaoDataHora;
	
	private String destinatarioNome = StringUtility.EMPTY;
	
	private String destinatarioCnpj = StringUtility.EMPTY;
	
	private String vlBaseIcms = StringUtility.EMPTY;
	
	private String vlIcms = StringUtility.EMPTY;
	
	private String vlTotalProdutos = StringUtility.EMPTY;
	
	private String vlDescontos = StringUtility.EMPTY;
	
	private String vlOutrasDespesas = StringUtility.EMPTY;
	
	private String vlQuantidade = StringUtility.EMPTY;
	
	private String pesoBruto = StringUtility.EMPTY;
	
	private String pesoLiquido = StringUtility.EMPTY;
	
	private String vlTotalNota = StringUtility.EMPTY;
	
	private List<String> produtos = new ArrayList<String>();
	
	private List<String> descontos = new ArrayList<String>();
	
	private ImpressoraMPT_Builder impressoraBuilder;
	
	public ImpressaoNotaBuilder(ImpressoraMPT_Builder impressoraBuilder) {
		this.impressoraBuilder = impressoraBuilder;
	}

	public ImpressaoNotaBuilder naturezaOperacao(String naturezaOperacao) {
		this.naturezaOperacao = naturezaOperacao;
		return this;
	}

	public ImpressaoNotaBuilder cfop(String cfop) {
		this.cfop = cfop;
		return this;
	}

	public ImpressaoNotaBuilder nfNumero(String nfNumero) {
		this.nfNumero = StringUtility.leftPad(nfNumero, 9, "0");
		return this;
	}

	public ImpressaoNotaBuilder nfSerie(String nfSerie) {
		this.nfSerie = StringUtility.leftPad(nfSerie, 3, "0");
		return this;
	}

	public ImpressaoNotaBuilder via(int via) {
		this.via = String.valueOf(via);
		return this;
	}

	public ImpressaoNotaBuilder emitidaContigencia(boolean emitidaContigencia) {
		this.emitidaContigencia = emitidaContigencia;
		return this;
	}

	public ImpressaoNotaBuilder chaveAcesso(String chaveAcesso) {
		this.chaveAcesso = chaveAcesso;
		return this;
	}

	public ImpressaoNotaBuilder protocoloAutorizacao(String protocoloAutorizacao) {
		this.protocoloAutorizacao = protocoloAutorizacao;
		return this;
	}

	public ImpressaoNotaBuilder emissaoDataHora(Date data, Date hora) {
		String emissaoDataHora = new StringBuilder()
		.append(FogasUtility.data.getStringByDateAndFormat(data, "dd/MM/yyyy"))
		.append(" ")
		.append(FogasUtility.data.getStringByDateAndFormat(hora, "HH:mm:ss"))
		.toString();
		
		this.emissaoDataHora = emissaoDataHora;
		return this;
	}

	public ImpressaoNotaBuilder emitente(FogasDados emitente) {
		this.emitente = emitente;
		return this;
	}

	public ImpressaoNotaBuilder destinatarioNome(Cliente destinatario) {
		String nome = new StringBuilder()
		.append(StringUtility.removeZeroEsquerdaString(destinatario.getTx_cod_cliente()))
		.append(" - ")
		.append(destinatario.getTx_nome())
		.toString();
		
		this.destinatarioNome = nome;
		return this;
	}

	public ImpressaoNotaBuilder destinatarioCnpj(String cnpj) {
		this.destinatarioCnpj = "CNPJ "+FogasUtility.string.cnpjFormatado(cnpj);
		return this;
	}
	
	public ImpressaoNotaBuilder produtos(Collection<NotaItem> produtos) {
		this.produtos = linhasImpressaoProdutos(produtos);
		return this;
	}
	
	public ImpressaoNotaBuilder descontos(NotaFiscal notaFiscal) {
		this.descontos = descontosImpressao(notaFiscal);
		return this;
	}

	public ImpressaoNotaBuilder valorBaseIcms(double valor) {
		this.vlBaseIcms = valorImpressao(valor);
		return this;
	}

	public ImpressaoNotaBuilder valorIcms(double valor) {
		this.vlIcms = valorImpressao(valor);
		return this;
	}

	public ImpressaoNotaBuilder valorTotalProdutos(double valor) {
		this.vlTotalProdutos = valorImpressao(valor);
		return this;
	}

	public ImpressaoNotaBuilder valorDescontos(double valor) {
		String valorDesc = valorImpressao(valor);
		if(valor < 0) {
			valorDesc = StringUtils.replace(valorDesc, "-", "");
			valorDesc = StringUtils.trim(valorDesc);
		}
		this.vlDescontos = valorDesc;
		return this;
	}

	public ImpressaoNotaBuilder valorOutrasDespesas(double valor) {
		this.vlOutrasDespesas = valorImpressao(valor);
		return this;
	}

	public ImpressaoNotaBuilder quantidade(double valor) {
		this.vlQuantidade = valorImpressao(valor);
		return this;
	}
	
	public ImpressaoNotaBuilder valorTotalNota(double valor) {
		this.vlTotalNota = valorImpressao(valor);
		return this;
	}

	public ImpressaoNotaBuilder pesoBruto(double valor) {
		this.pesoBruto = valorImpressao(valor);
		return this;
	}

	public ImpressaoNotaBuilder pesoLiquido(double valor) {
		this.pesoLiquido = valorImpressao(valor);
		return this;
	}
	
	private List<String> descontosImpressao(NotaFiscal notaFiscal) {
		List<String> impressao = new ArrayList<String>();
		
		List<DescontosDto> descontos = NotaFiscalEngine.getDescontosNota(notaFiscal);
		if(!descontos.isEmpty()) {
			for(DescontosDto condicao: descontos) {
				String vltotal = FogasUtility.string.currencyFormat(condicao.getValorTotal().doubleValue());
				String descontoImpressao = condicao.getCondicoesEnum().getDescricao() +" "+ StringUtility.replace(vltotal, "R$", "");
				impressao.add(descontoImpressao);
			}
		}
		
		return impressao;
	}
	
	private List<String> linhasImpressaoProdutos(Collection<NotaItem> items) {
		List<String> impressao = new ArrayList<String>();
		impressao.add("COD| DESC PRODUTO|UND|QTDE |VL.UNIT.| VL.TOTAL");
		
		for (NotaItem item : items) {
			impressao.addAll(linhasImpressaoPorProduto(item));
		}
		
		return impressao;
	}
	
	private List<String> linhasImpressaoPorProduto(NotaItem item) {
		List<String> impressao = new ArrayList<String>();
		
		int i = 0;
		List<String> linhasDescricaoProduto = calculaLinhasPorDescricaoProduto(item.getTx_material().getTx_desc_mat());
		for (String descricao : linhasDescricaoProduto) {
			String linhaImpressao = "";
			
			if(i == 0) {
				String vlrUnit = FogasUtility.string.currencyFormat(item.getVl_unitario().doubleValue());
				String vlrTotal = FogasUtility.string.currencyFormat(item.getVl_total().doubleValue());
				
				linhaImpressao += StringUtility.leftPad(item.getTx_material().getTx_cod_material(), 3, " ") +"|";
				linhaImpressao += StringUtility.leftPad(descricao, 13, " ") +"|";
				linhaImpressao += StringUtility.leftPad(item.getTx_material().getTx_und(), 3, " ") +"|";
				linhaImpressao += StringUtility.leftPad(String.valueOf(item.getNb_qtde().doubleValue()), 5, " ") +"|";
				linhaImpressao += StringUtility.leftPad(StringUtility.replace(vlrUnit, "R$", ""), 8, " ") +"|";
				linhaImpressao += StringUtility.leftPad(StringUtility.replace(vlrTotal, "R$", ""), 10, " ");
				impressao.add(linhaImpressao);
			} else {
				linhaImpressao += StringUtility.leftPad("", 3, " ") +"|";
				linhaImpressao += StringUtility.leftPad(descricao, 13, " ") +"|";
				linhaImpressao += StringUtility.leftPad("", 3, " ") +"|";
				linhaImpressao += StringUtility.leftPad("", 5, " ") +"|";
				linhaImpressao += StringUtility.leftPad("", 8, " ") +"|";
				linhaImpressao += StringUtility.leftPad("", 10, " ");
				impressao.add(linhaImpressao);
			}
			i++;
		} 
		
		return impressao;
	}
	
	private List<String> calculaLinhasPorDescricaoProduto(String produto) {
		List<String> linhas = new ArrayList<String>();
		
		String palavra = "";
		int i = 1;
		int index = 0;
		for(char caracter: produto.toCharArray()) {
			palavra += String.valueOf(caracter);
			if(i == 13) {
				String normalizada = StringUtility.normalizeSpace(palavra);
				if(StringUtility.isNotEmpty(normalizada))
					linhas.add(normalizada);
				
				palavra = "";
				i = 0;
			}
			i++;
			index++;
			
			if(index == produto.toCharArray().length) {
				String normalizada = StringUtility.normalizeSpace(palavra);
				if(StringUtility.isNotEmpty(normalizada))
					linhas.add(normalizada);
			}
		}
		
		return linhas;
	}
	
	private String valorImpressao(double valor) {
		String valorImpressao = FogasUtility.string.currencyFormat(valor);
		return StringUtility.replace(valorImpressao, "R$", "");
	}
	
	/**
	 * imprimi a nota na impressora
	 * 
	 * @author andre.nascimento
	 * @throws ImpressoraMPTException 
	 */
	public void imprimir() throws ImpressoraMPTException {
		//LOGO FOGAS
		impressoraBuilder.imprimirLogo();
		
		//CABECALHO
		impressoraBuilder
		.imprimirLinha("RECEBEMOS DA SOCIEDADE FOGAS LTDA")
		.imprimirLinha("PRODUTOS CONSTANTES DA NFE     NUMERO "+nfNumero)
		.imprimirLinha("                               SERIE "+nfSerie)
		.imprimirLinha("IDENTIFICACAO/ASSINATURA", ALIGN.AL_RIGHT)
		.imprimirLinhaBranco()
		.imprimirLinha("___/___/___ ___________________________________", 40, true, false, false, ALIGN.AL_CENTER)
		.imprimirLinhaBranco()
		.imprimirLinha("DANFE SIMPLIFICADO", ALIGN.AL_CENTER)
		.imprimirLinha("DOCUMENTO AUXILIAR DA", ALIGN.AL_CENTER)
		.imprimirLinha("NOTA FISCAL ELETRONICA", ALIGN.AL_CENTER)
		.imprimirLinhaBranco()
		.imprimirLinha("1-SAIDA VIA - "+via, ALIGN.AL_RIGHT);
		
		if(emitidaContigencia) {
			impressoraBuilder
			.imprimirLinhaBranco()
			.imprimirLinha("(Emitido em Contingencia)", 30, false, false, false, ALIGN.AL_CENTER);
		}
		
		//CHAVE ACESSO PROTOCOLO
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirCodigoBarras(chaveAcesso)
		.imprimirLinhaBranco()
		.imprimirLinha("CHAVE DE ACESSO", true)
		.imprimirLinha(chaveAcesso, 10)
		.imprimirLinha("PROTOCOLO DE AUTORIZACAO", true);
		if(StringUtility.isNotEmpty(protocoloAutorizacao)) {
			impressoraBuilder.imprimirLinha(protocoloAutorizacao, 10);
		}
		
		//N.OP CFOP
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirLinha("N.OP:"+naturezaOperacao)
		.imprimirLinha("CFOP:"+cfop);
		
		//EMITENTE
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirLinha("EMITENTE", true)
		.imprimirLinha(StringUtility.upperCase(emitente.getRazao()))
	    .imprimirLinha(StringUtility.upperCase(emitente.getLogradouro()))
	    .imprimirLinha(StringUtility.upperCase(emitente.getBairro() +" - "+ emitente.getCidade() +" - "+ emitente.getUf()))
	    .imprimirLinha("CEP: "+emitente.getCep()+" TEL: "+emitente.getTelefone1())
	    .imprimirLinha("WWW.FOGAS.COM.BR")
	    .imprimirLinha("CNPJ: "+FogasUtility.string.cnpjFormatado(emitente.getCnpj()))
	    .imprimirLinha("IE: "+emitente.getInscEstadual());
		
		//DESTINATARIO
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirLinha("DESTINATARIO", true)
		.imprimirLinha(destinatarioNome)
	    .imprimirLinha(destinatarioCnpj);
		
		//EMISSAO DATA HORA
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirLinha("EMISSAO: "+emissaoDataHora);

		//PRODUTOS
		int i = 0;
		for (String linhaImpressao : produtos) {
			if(i == 0) {
				impressoraBuilder
				.imprimirLinhaBranco()
				.imprimirLinha(linhaImpressao, true);
			} else {
				impressoraBuilder.imprimirLinha(linhaImpressao);
			}
			i++;
		}
		
		//DESCONTOS
		i = 0;
		for (String linhaImpressao : descontos) {
			if(i == 0) {
				impressoraBuilder.imprimirLinhaBranco();
			} else {
				impressoraBuilder.imprimirLinha(linhaImpressao);
			}
			i++;
		}
		
		//DESCRICOES
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirLinha("GLP ja tributado ate o consumidor final art.5")
		.imprimirLinha("Dec. 19.945/99. Saida Isenta")
		.imprimirLinha("Obs: vasilhame sujeito retorno nao inc. icms")
		.imprimirLinha("Conv. 88/91, 10/92 e 103/96 Confaz", 20)
		.imprimirLinha("Dec. que o GLP esta condicionado p/ suportar os")
		.imprimirLinha("Riscos normais de carreg, descarreg. e transp.")
		.imprimirLinha("Classe 2 n. onu 1075 n. guia 22", 30);
		
		//TOTAIS NOTA
		impressoraBuilder
		.imprimirLinhaBranco()
		.imprimirLinha("Base de calculo I.C.M.S.           "+vlBaseIcms)
		.imprimirLinha("Valor do I.C.M.S.                  "+vlIcms)
		.imprimirLinha("Valor total dos produtos           "+vlTotalProdutos)
		.imprimirLinha("Descontos                          "+vlDescontos)
		.imprimirLinha("Outras despesas                    "+vlOutrasDespesas)
		.imprimirLinha("Quantidade                         "+vlQuantidade)
		.imprimirLinha("Peso bruto                         "+pesoBruto+"KG")
		.imprimirLinha("Peso liquido                       "+pesoLiquido+"KG")
		.imprimirLinha("Valor total da nota                "+vlTotalNota);
	}
}